package com.android.systemui.statusbar.board;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.media.projection.MediaProjectionManager;
import android.media.projection.IMediaProjectionManager;
import android.media.projection.IMediaProjection;
import android.media.MediaRecorder;
import android.media.AudioRecord;
import android.media.AudioFormat;

import android.media.projection.MediaProjection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.Environment;
import android.util.Log;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.Display;
import android.view.WindowManager;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;
import android.widget.Toast;
import android.text.TextUtils;
import android.graphics.Point;

import java.io.File;
import java.io.IOException;

import com.android.internal.app.AlertActivity;
import com.android.internal.app.AlertController;
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.SystemUIDialog;

import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;

/**
 * 录屏工具类
 * start/end sendbroadcast to board (end with path)
 */
public class MediaProjectionUtil {
    private static final String TAG = "MediaProjectionUtil";

    public static String BOARD_PATH = Environment.getExternalStorageDirectory() + "/board/";
    public static String BOARD_RECORD_PATH = BOARD_PATH + "record/";

    Context mContext;
    private boolean mPermanentGrant;
    private String mPackageName;
    private int mUid;
    private IMediaProjectionManager mService;
    private IMediaProjection iMediaProjection = null;
    private MediaProjection projection;
    private MediaRecorder mediaRecorder;
    private VirtualDisplay virtualDisplay;

    public boolean isRunning() {
        return running;
    }

    private boolean running = false;
    private int width = 720;
    private int height = 1080;
    private int dpi;

    private static MediaProjectionUtil sInstance;

    public static MediaProjectionUtil getInstance(Context context) {
        if (sInstance == null) {
            sInstance = new MediaProjectionUtil(context);
        }
        return sInstance;
    }

    private MediaProjectionUtil(Context context) {
        mContext = context;
        IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE);
        mService = IMediaProjectionManager.Stub.asInterface(b);

        mUid = mContext.getApplicationInfo().uid;
        mPackageName = mContext.getApplicationInfo().packageName;
        try {
            iMediaProjection = mService.createProjection(mUid, mPackageName,
                    MediaProjectionManager.TYPE_SCREEN_CAPTURE, true);
        } catch (RemoteException e) {
            Log.e("mpu", " get iMediaProjection fail," + e);
            e.printStackTrace();
        }

        createDir(BOARD_PATH);
        createDir(BOARD_RECORD_PATH);
        initConfig();
    }

    public boolean startRecord() {
        mediaRecorder = new MediaRecorder();
        projection = new MediaProjection(mContext, iMediaProjection);
        if (projection == null || running) return false;

        Log.e(TAG, " startRecord");
        initRecorder();
        createVirtualDisplay();
        try {
            mediaRecorder.start();
            running = true;
            Log.e(TAG, " startRecord, mediaRecorder.start");
        } catch (Exception e) {
            Log.e(TAG, " startRecord 录屏发生了Error," + e);
            //销毁工作
            mediaRecorder.reset();
            mediaRecorder.release();
            mediaRecorder = null;
            virtualDisplay.release();
            projection.stop();
            running = false;
            return false;
        }
        return true;
    }

    public boolean stopRecord() {
        if (!running) {
            return false;
        }
        running = false;
        if (mediaRecorder != null) {
            mediaRecorder.stop();
            mediaRecorder.release();
            mediaRecorder = null;
        }
        virtualDisplay.release();
        projection.stop();
        return true;
    }

    private void createVirtualDisplay() {
        virtualDisplay = projection.createVirtualDisplay("MainScreen", width, height, dpi,
                DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mediaRecorder.getSurface(), null, null);
    }

    private void initRecorder() {
        boolean micAvailability = validateMicAvailability();
        Log.d(TAG, "micAvailability" + micAvailability);
        if (micAvailability) {
            mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        }
        mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
        mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
        mediaRecorder.setOutputFile(getsaveDirectory());
        mediaRecorder.setVideoSize(width, height);
        mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        if (micAvailability) {
            mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
            if (isHasUsbMic()) {
                int samplingRate = getUsbMicSampleRate();
                mediaRecorder.setAudioSamplingRate(samplingRate);
                Log.d(TAG, "has usb mic samplingRate = " + samplingRate);
            } else {
                mediaRecorder.setAudioSamplingRate(44100);
            }
        }
        mediaRecorder.setVideoEncodingBitRate(5 * 1024 * 1024);
        mediaRecorder.setVideoFrameRate(30);
        try {
            mediaRecorder.prepare();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public String getsaveDirectory() {
        String desPath = BOARD_RECORD_PATH + System.currentTimeMillis() + ".mp4";
        File file = new File(desPath);
        return desPath;
    }

    public void initConfig() {
        Display mDisplay = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE))
                .getDefaultDisplay();
        Point mCurrentDisplaySize = new Point();
        DisplayMetrics mDisplayMetrics = new DisplayMetrics();
        mDisplay.getRealMetrics(mDisplayMetrics);
        width = mDisplayMetrics.widthPixels;
        height = mDisplayMetrics.heightPixels;
        dpi = mDisplayMetrics.densityDpi;
    }

    private File createDir(String path) {
        if (TextUtils.isEmpty(path)) return null;
        File file = new File(path);
        boolean hasFile = true;
        if (!file.exists()) hasFile = file.mkdir();
        return hasFile ? file : null;
    }

    /**
     * 检测麦克风是否可用，被占用的时候会return false
     */
    private boolean validateMicAvailability() {
        Boolean available = true;
        AudioRecord recorder =
                new AudioRecord(MediaRecorder.AudioSource.MIC, 44100,
                        AudioFormat.CHANNEL_IN_MONO,
                        AudioFormat.ENCODING_DEFAULT, 44100);
        try {
            if (recorder.getRecordingState() != AudioRecord.RECORDSTATE_STOPPED) {
                available = false;

            }

            recorder.startRecording();
            if (recorder.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING) {
                recorder.stop();
                available = false;

            }
            recorder.stop();
        } finally {
            recorder.release();
            recorder = null;
        }

        return available;
    }

    private boolean isHasUsbMic() {
        ShellUtils.CommandResult result = ShellUtils.execCommand("ls /proc/asound/ | grep card3", true, true);
        if (TextUtils.equals(result.successMsg, "card3"))
            return true;
        return false;
    }

    private int getUsbMicSampleRate() {
        ShellUtils.CommandResult result = ShellUtils.execCommand("cat proc/asound/card3/stream0", true, true);
        if (result.successMsg == null) return 8000;
        int pos = result.successMsg.indexOf("Capture");
        if (pos == -1) return 8000;
        String captureMsg = result.successMsg.substring(pos);
        if (captureMsg.contains("44100"))
            return 44100;
        else if (captureMsg.contains("48000"))
            return 48000;
        else if (captureMsg.contains("32000"))
            return 32000;
        else
            return 8000;
    }
}
